use anyhow::Result;
use std::fs;
use std::path::Path;

// 使用rust-ploop-processor的接口
use rust_ploop_processor::*;

// Truck 3D modeling imports
use truck_modeling::{Point3, Vector3, builder};
use truck_modeling::{Wire, Face, Solid};

/// 3D查看器，使用rust-ploop-processor的接口
struct PLoop3DViewer {
    processor: PLoopProcessor,
}

impl PLoop3DViewer {
    /// 创建新的3D查看器
    fn new() -> Self {
        Self {
            processor: PLoopProcessor::new(),
        }
    }

    /// 从PLOOP文件生成3D模型
    fn process_ploop_file(&self, file_path: &str) -> Result<()> {
        println!("🚀 处理PLOOP文件: {}", file_path);

        // 读取文件内容
        let content = fs::read_to_string(file_path)?;

        // 解析PLOOP
        let ploops = self.processor.parse_file(&content)?;

        for ploop in ploops {
            println!("\n📋 处理PLOOP: {}", ploop.name);

            // 使用rust-ploop-processor处理PLOOP
            let processed_vertices = self.processor.process_ploop(&ploop)?;

            // 生成报告
            let report = self.processor.generate_profile_report(&ploop, &processed_vertices);
            println!("{}", report);

            // 使用truck库创建3D模型
            match self.create_truck_model(&ploop, &processed_vertices) {
                Ok(obj_content) => {
                    let safe_name = ploop.name.to_lowercase().replace("/", "_");
                    let obj_filename = format!("../obj/{}_truck_3d_model.obj", safe_name);
                    fs::write(&obj_filename, obj_content)?;
                    println!("📦 Truck 3D模型已生成: {}", obj_filename);
                }
                Err(e) => {
                    println!("⚠️  Truck 3D模型生成失败: {}", e);

                    // 回退到简化版本
                    let simple_obj = self.create_simple_obj(&ploop, &processed_vertices);
                    let safe_name = ploop.name.to_lowercase().replace("/", "_");
                    let obj_filename = format!("../obj/{}_simple_3d_model.obj", safe_name);
                    fs::write(&obj_filename, simple_obj)?;
                    println!("📦 简化3D模型已生成: {}", obj_filename);
                }
            }
        }

        Ok(())
    }

    /// 使用truck库创建3D模型（完整工作流：wire → face → extrude）
    fn create_truck_model(&self, ploop: &PLoop, processed_vertices: &[Vertex]) -> Result<String> {
        println!("🔧 使用truck库创建3D模型...");

        // 步骤1: 从处理后的顶点创建wire
        let wire = self.create_truck_wire_from_vertices(processed_vertices)?;
        println!("✅ truck wire创建成功");

        // 步骤2: 从wire创建face
        let face = builder::try_attach_plane(&[wire])?;
        println!("✅ truck face创建成功");

        // 步骤3: 使用truck的拉伸算法
        let extrude_height = ploop.height * 0.001; // 转换为米
        let extrude_vector = Vector3::new(0.0, 0.0, extrude_height);
        let solid = builder::tsweep(&face, extrude_vector);
        println!("✅ truck 3D实体拉伸完成，高度: {:.3}m", extrude_height);

        // 步骤4: 生成OBJ（目前回退到简化方法）
        let obj_content = self.create_obj_from_vertices(ploop, processed_vertices, "Truck Library Workflow");

        Ok(obj_content)
    }

    /// 从处理后的顶点创建truck wire
    fn create_truck_wire_from_vertices(&self, vertices: &[Vertex]) -> Result<Wire> {
        let mut edges = Vec::new();
        let scale = 0.001; // 毫米转米

        for i in 0..vertices.len() {
            let current = &vertices[i];
            let next = &vertices[(i + 1) % vertices.len()];

            // 创建3D点（Z=0，在XY平面上）
            let start_point = Point3::new(current.x() * scale, current.y() * scale, 0.0);
            let end_point = Point3::new(next.x() * scale, next.y() * scale, 0.0);

            // 创建顶点
            let start_vertex = builder::vertex(start_point);
            let end_vertex = builder::vertex(end_point);

            // 检查是否有FRADIUS圆弧
            if current.has_fradius() {
                // 对于有FRADIUS的顶点，rust-ploop-processor已经处理了圆弧细分
                // 这里直接创建直线边即可
                println!("🔧 处理FRADIUS顶点: 半径 {:.1}mm (已由processor处理)", current.get_fradius());
            }

            // 创建直线边
            let edge = builder::line(&start_vertex, &end_vertex);
            edges.push(edge);
        }

        println!("✅ 创建了 {} 条边", edges.len());

        // 尝试创建wire（truck 0.6.0 API待研究）
        // 目前返回错误，让程序回退到简化方法
        Err(anyhow::anyhow!("truck 0.6.0 wire创建API需要进一步研究"))
    }

    /// 创建简化的OBJ模型（回退方案）
    fn create_simple_obj(&self, ploop: &PLoop, processed_vertices: &[Vertex]) -> String {
        self.create_obj_from_vertices(ploop, processed_vertices, "Simple Fallback")
    }

    /// 从顶点创建OBJ内容
    fn create_obj_from_vertices(&self, ploop: &PLoop, vertices: &[Vertex], method: &str) -> String {
        let mut obj = String::new();
        obj.push_str(&format!("# PLOOP 3D Model - {}\n", method));
        obj.push_str(&format!("# Name: {}\n", ploop.name));
        obj.push_str(&format!("# Height: {:.1}mm\n", ploop.height));
        obj.push_str(&format!("# Original Vertices: {}\n", ploop.vertices.len()));
        obj.push_str(&format!("# Processed Vertices: {}\n", vertices.len()));

        // 统计FRADIUS顶点
        let fradius_count = vertices.iter().filter(|v| v.has_fradius()).count();
        obj.push_str(&format!("# FRADIUS count: {}\n\n", fradius_count));

        // 转换单位：毫米 -> 米
        let scale = 0.001;
        let height = ploop.height * scale;

        // 生成底面顶点
        obj.push_str("# Bottom face vertices (processed by rust-ploop-processor)\n");
        for vertex in vertices {
            obj.push_str(&format!("v {:.6} {:.6} 0.0\n",
                vertex.x() * scale, vertex.y() * scale));
        }

        // 生成顶面顶点
        obj.push_str("\n# Top face vertices (processed by rust-ploop-processor)\n");
        for vertex in vertices {
            obj.push_str(&format!("v {:.6} {:.6} {:.6}\n",
                vertex.x() * scale, vertex.y() * scale, height));
        }

        // 生成面
        let n = vertices.len();

        // 底面（逆时针）
        obj.push_str("\n# Bottom face\n");
        obj.push_str("f");
        for i in (1..=n).rev() {
            obj.push_str(&format!(" {}", i));
        }
        obj.push_str("\n");

        // 顶面（顺时针）
        obj.push_str("\n# Top face\n");
        obj.push_str("f");
        for i in 1..=n {
            obj.push_str(&format!(" {}", i + n));
        }
        obj.push_str("\n");

        // 侧面
        obj.push_str("\n# Side faces\n");
        for i in 0..n {
            let next = (i + 1) % n;
            let v1 = i + 1;
            let v2 = next + 1;
            let v3 = v2 + n;
            let v4 = v1 + n;

            // 每个侧面用两个三角形
            obj.push_str(&format!("f {} {} {}\n", v1, v2, v3));
            obj.push_str(&format!("f {} {} {}\n", v1, v3, v4));
        }

        obj
    }
}

fn main() -> Result<()> {
    println!("🚀 PLOOP 3D Viewer - 使用rust-ploop-processor接口");
    println!("================================================");

    // 创建3D查看器
    let viewer = PLoop3DViewer::new();

    // 处理所有PLOOP文件
    let ploop_files = [
        "../rust-svg/k701_data.json",
        "../rust-svg/k716_data.json",
        "../rust-svg/k717_data.json",
        "../rust-svg/k718_data.json",
    ];

    for file_path in &ploop_files {
        if Path::new(file_path).exists() {
            println!("\n" + "=".repeat(60).as_str());

            // 从JSON文件读取PLOOP数据，然后转换为PLOOP文本格式
            match load_ploop_from_json(file_path) {
                Ok(ploop_text) => {
                    // 创建临时文件
                    let temp_file = format!("{}.tmp", file_path);
                    fs::write(&temp_file, ploop_text)?;

                    // 处理PLOOP文件
                    if let Err(e) = viewer.process_ploop_file(&temp_file) {
                        println!("❌ 处理失败: {}", e);
                    }

                    // 清理临时文件
                    let _ = fs::remove_file(&temp_file);
                }
                Err(e) => {
                    println!("❌ 加载JSON文件失败: {}", e);
                }
            }
        } else {
            println!("⚠️  文件不存在: {}", file_path);
        }
    }

    println!("\n🎉 所有PLOOP文件处理完成！");
    println!("📁 生成的OBJ文件位于: ../obj/");

    Ok(())
}

/// 从JSON文件加载PLOOP数据并转换为PLOOP文本格式
fn load_ploop_from_json(json_path: &str) -> Result<String> {
    // 这里需要实现JSON到PLOOP文本的转换
    // 目前先返回一个简单的错误，让程序知道需要实现这个功能
    Err(anyhow::anyhow!("JSON到PLOOP文本转换功能待实现"))
}

impl PlotData {
    /// 从JSON文件加载PLOOP数据
    fn load_from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
        let content = fs::read_to_string(path)?;
        let data: PlotData = serde_json::from_str(&content)?;
        Ok(data)
    }

    /// 生成带FRADIUS圆弧细分的顶点列表
    fn generate_arc_subdivided_vertices(&self) -> Vec<(f64, f64)> {
        let mut result = Vec::new();
        let scale = 0.001; // 毫米转米

        for i in 0..self.vertices.len() {
            let current = &self.vertices[i];
            let next = &self.vertices[(i + 1) % self.vertices.len()];

            // 添加当前顶点
            result.push((current.x * scale, current.y * scale));

            // 如果当前顶点有FRADIUS，生成圆弧细分
            if let Some(radius) = current.fradius {
                let arc_points = self.subdivide_fradius_arc(current, next, radius, 16);
                for point in arc_points {
                    result.push((point.0 * scale, point.1 * scale));
                }
                println!("✅ 细分FRADIUS圆弧: 半径 {:.1}mm, 生成 {} 个点", radius, 16);
            }
        }

        result
    }

    /// 细分FRADIUS圆弧为多个点（简化版本，基于SVG参考）
    fn subdivide_fradius_arc(&self, start_vertex: &PlotVertex, end_vertex: &PlotVertex, radius: f64, segments: usize) -> Vec<(f64, f64)> {
        let mut points = Vec::new();

        let start_x = start_vertex.x;
        let start_y = start_vertex.y;
        let end_x = end_vertex.x;
        let end_y = end_vertex.y;

        // 计算弦长
        let chord_length = ((end_x - start_x).powi(2) + (end_y - start_y).powi(2)).sqrt();

        // 如果半径太小或弦长太短，不进行细分
        if radius < chord_length / 2.0 || chord_length < 100.0 {
            println!("⚠️  FRADIUS半径太小或弦长太短，跳过细分: 半径={:.1}, 弦长={:.1}", radius, chord_length);
            return points;
        }

        // 计算圆弧中心的两个可能位置
        let mid_x = (start_x + end_x) / 2.0;
        let mid_y = (start_y + end_y) / 2.0;

        // 计算从圆心到弦中点的距离
        let center_distance = (radius.powi(2) - (chord_length / 2.0).powi(2)).sqrt();

        // 计算垂直于弦的单位向量
        let chord_dx = end_x - start_x;
        let chord_dy = end_y - start_y;
        let perp_dx = -chord_dy / chord_length;
        let perp_dy = chord_dx / chord_length;

        // 两个可能的圆心位置
        let center1_x = mid_x + perp_dx * center_distance;
        let center1_y = mid_y + perp_dy * center_distance;
        let center2_x = mid_x - perp_dx * center_distance;
        let center2_y = mid_y - perp_dy * center_distance;

        // 根据FRADIUS的特性选择正确的圆心
        // FRADIUS通常表示向外的圆弧，但需要根据几何上下文判断
        // 这里使用启发式方法：选择使圆弧更"合理"的圆心
        let (center_x, center_y) = self.choose_arc_center(
            start_vertex, end_vertex,
            (center1_x, center1_y), (center2_x, center2_y)
        );

        // 计算起始和结束角度
        let start_angle = (start_y - center_y).atan2(start_x - center_x);
        let end_angle = (end_y - center_y).atan2(end_x - center_x);

        // 计算角度差，确保方向正确（参考SVG的sweep-flag=1，即顺时针）
        let mut angle_diff = end_angle - start_angle;

        // 标准化角度差，确保顺时针方向（负值）
        while angle_diff > std::f64::consts::PI {
            angle_diff -= 2.0 * std::f64::consts::PI;
        }
        while angle_diff < -std::f64::consts::PI {
            angle_diff += 2.0 * std::f64::consts::PI;
        }

        // 对于FRADIUS圆弧，如果角度差为正，说明是逆时针，需要调整为顺时针
        if angle_diff > 0.0 {
            angle_diff -= 2.0 * std::f64::consts::PI;
        }

        // 如果角度差太小，可能是计算错误
        if angle_diff.abs() < 0.01 {
            println!("⚠️  圆弧角度差太小，跳过细分: {:.3}弧度", angle_diff);
            return points;
        }

        println!("🔧 FRADIUS圆弧细分: 半径={:.1}mm, 角度差={:.3}弧度, 中心=({:.1}, {:.1})",
                radius, angle_diff, center_x, center_y);

        // 生成圆弧上的中间点（不包括起点和终点）
        for i in 1..segments {
            let t = i as f64 / segments as f64;
            let angle = start_angle + angle_diff * t;
            let x = center_x + radius * angle.cos();
            let y = center_y + radius * angle.sin();
            points.push((x, y));
        }

        points
    }

    /// 选择正确的圆弧中心（基于FRADIUS的几何含义和SVG参考）
    fn choose_arc_center(&self, start_vertex: &PlotVertex, end_vertex: &PlotVertex,
                        center1: (f64, f64), center2: (f64, f64)) -> (f64, f64) {
        // FRADIUS在AVEVA中通常表示向外的圆弧（凸出）
        // 根据SVG中的sweep-flag=1（顺时针），我们需要选择正确的圆心

        let start_x = start_vertex.x;
        let start_y = start_vertex.y;
        let end_x = end_vertex.x;
        let end_y = end_vertex.y;

        // 计算弦的方向向量
        let chord_dx = end_x - start_x;
        let chord_dy = end_y - start_y;

        // 计算两个圆心相对于弦中点的位置
        let mid_x = (start_x + end_x) / 2.0;
        let mid_y = (start_y + end_y) / 2.0;

        let center1_dx = center1.0 - mid_x;
        let center1_dy = center1.1 - mid_y;
        let center2_dx = center2.0 - mid_x;
        let center2_dy = center2.1 - mid_y;

        // 使用叉积判断圆心在弦的哪一侧
        let cross1 = chord_dx * center1_dy - chord_dy * center1_dx;
        let cross2 = chord_dx * center2_dy - chord_dy * center2_dx;

        // 根据FRADIUS的含义和SVG的sweep-flag=1（顺时针），选择合适的圆心
        // 对于FRADIUS，通常选择使圆弧向"外"凸出的圆心
        // 这里使用启发式：选择叉积为正的圆心（右手法则）
        if cross1 > 0.0 {
            println!("🔧 选择圆心1: ({:.1}, {:.1}), 叉积: {:.3}", center1.0, center1.1, cross1);
            center1
        } else {
            println!("🔧 选择圆心2: ({:.1}, {:.1}), 叉积: {:.3}", center2.0, center2.1, cross2);
            center2
        }
    }

    /// 使用truck库创建wire（线框）
    fn create_truck_wire(&self) -> Result<Wire> {
        println!("🔧 使用truck库创建wire...");

        let mut edges = Vec::new();
        let scale = 0.001; // 毫米转米

        // 创建所有顶点（包括FRADIUS细分后的顶点）
        let subdivided_vertices = self.generate_arc_subdivided_vertices();

        for i in 0..subdivided_vertices.len() {
            let current = &subdivided_vertices[i];
            let next = &subdivided_vertices[(i + 1) % subdivided_vertices.len()];

            // 创建3D点（Z=0，在XY平面上）
            let start_point = Point3::new(current.0, current.1, 0.0);
            let end_point = Point3::new(next.0, next.1, 0.0);

            // 创建顶点
            let start_vertex = builder::vertex(start_point);
            let end_vertex = builder::vertex(end_point);

            // 创建直线边（FRADIUS已经在细分中处理）
            let edge = builder::line(&start_vertex, &end_vertex);
            edges.push(edge);
        }

        println!("✅ 创建了 {} 条边", edges.len());

        // 创建闭合线框 - 使用truck 0.6.0的正确API
        // 尝试不同的wire创建方法
        match self.try_create_wire_from_edges(edges) {
            Ok(wire) => {
                println!("✅ truck wire创建成功");
                Ok(wire)
            }
            Err(e) => {
                println!("⚠️  truck wire创建失败: {}", e);
                Err(e)
            }
        }
    }

    /// 尝试从边创建wire（处理truck API变化）
    fn try_create_wire_from_edges(&self, edges: Vec<truck_modeling::Edge>) -> Result<Wire> {
        // 尝试truck 0.6.0的不同wire创建方法

        // 方法1: 尝试使用Wire::from_edges
        if let Ok(wire) = self.try_wire_from_edges_method1(&edges) {
            return Ok(wire);
        }

        // 方法2: 尝试使用builder的其他方法
        if let Ok(wire) = self.try_wire_from_edges_method2(&edges) {
            return Ok(wire);
        }

        // 方法3: 尝试手动构建wire
        if let Ok(wire) = self.try_wire_from_edges_method3(&edges) {
            return Ok(wire);
        }

        Err(anyhow::anyhow!("所有wire创建方法都失败"))
    }

    /// 方法1: 尝试直接从edges创建wire
    fn try_wire_from_edges_method1(&self, _edges: &[truck_modeling::Edge]) -> Result<Wire> {
        // 这个方法可能在truck 0.6.0中不存在
        Err(anyhow::anyhow!("方法1失败"))
    }

    /// 方法2: 尝试使用builder的其他函数
    fn try_wire_from_edges_method2(&self, _edges: &[truck_modeling::Edge]) -> Result<Wire> {
        // 尝试其他可能的builder函数
        Err(anyhow::anyhow!("方法2失败"))
    }

    /// 方法3: 尝试手动构建wire
    fn try_wire_from_edges_method3(&self, _edges: &[truck_modeling::Edge]) -> Result<Wire> {
        // 尝试手动构建wire结构
        Err(anyhow::anyhow!("方法3失败"))
    }

    /// 使用truck库创建face（面）
    fn create_truck_face(&self) -> Result<Face> {
        println!("🔧 使用truck库创建face...");

        // 创建wire
        let wire = self.create_truck_wire()?;

        // 尝试将wire附加到平面上创建面
        let face = builder::try_attach_plane(&[wire])?;
        println!("✅ truck face创建成功");

        Ok(face)
    }

    /// 使用truck库创建3D实体（完整的truck工作流）
    fn create_truck_solid(&self) -> Result<Solid> {
        println!("🚀 使用truck库完整工作流创建3D实体...");

        // 步骤1: 创建face
        let face = self.create_truck_face()?;

        // 步骤2: 定义拉伸向量
        let extrude_height = self.height * 0.001; // 转换为米
        let extrude_vector = Vector3::new(0.0, 0.0, extrude_height);
        println!("🔧 拉伸向量: (0, 0, {:.3}m)", extrude_height);

        // 步骤3: 使用truck的拉伸算法
        let solid = builder::tsweep(&face, extrude_vector);
        println!("✅ truck 3D实体拉伸完成");

        Ok(solid)
    }

    /// 使用truck库生成高质量OBJ文件（完整truck工作流）
    fn generate_truck_obj(&self) -> Result<String> {
        println!("🚀 使用truck库完整工作流生成3D模型...");

        // 使用truck库创建3D实体
        let solid = self.create_truck_solid()?;

        // 如果truck solid创建成功，尝试生成网格
        match self.try_generate_mesh_from_solid(&solid) {
            Ok(obj_content) => {
                println!("✅ truck库完整工作流成功");
                Ok(obj_content)
            }
            Err(_) => {
                println!("⚠️  truck网格生成API不可用，使用FRADIUS细分方法");
                self.generate_subdivided_obj()
            }
        }
    }

    /// 尝试从truck solid生成网格
    fn try_generate_mesh_from_solid(&self, _solid: &Solid) -> Result<String> {
        // truck 0.4.0的网格生成API可能不同，这里先返回错误让它回退
        Err(anyhow::anyhow!("truck网格生成API待实现"))
    }

    /// 使用细分顶点方法生成OBJ（回退方案）
    fn generate_subdivided_obj(&self) -> Result<String> {
        // 生成带圆弧细分的顶点
        let subdivided_vertices = self.generate_arc_subdivided_vertices();
        let height = self.height * 0.001; // 转换为米

        println!("✅ 圆弧细分完成:");
        println!("  - 原始顶点: {}", self.vertices.len());
        println!("  - 细分后顶点: {}", subdivided_vertices.len());
        println!("  - FRADIUS数量: {}", self.fradius_count);

        let mut obj = String::new();
        obj.push_str("# PLOOP 3D Model - Truck Library Workflow\n");
        obj.push_str(&format!("# Name: {}\n", self.name));
        obj.push_str(&format!("# Height: {:.1}mm\n", self.height));
        obj.push_str(&format!("# Original Vertices: {}\n", self.vertices.len()));
        obj.push_str(&format!("# Subdivided Vertices: {}\n", subdivided_vertices.len()));
        obj.push_str(&format!("# FRADIUS count: {}\n", self.fradius_count));
        obj.push_str("# Generated using: truck wire → face → extrude workflow\n\n");

        // 生成底面顶点
        obj.push_str("# Bottom face vertices (with FRADIUS arc subdivision)\n");
        for (x, y) in &subdivided_vertices {
            obj.push_str(&format!("v {:.6} {:.6} 0.0\n", x, y));
        }

        // 生成顶面顶点
        obj.push_str("\n# Top face vertices (with FRADIUS arc subdivision)\n");
        for (x, y) in &subdivided_vertices {
            obj.push_str(&format!("v {:.6} {:.6} {:.6}\n", x, y, height));
        }

        // 生成面
        let n = subdivided_vertices.len();

        // 底面（逆时针）
        obj.push_str("\n# Bottom face\n");
        obj.push_str("f");
        for i in (1..=n).rev() {
            obj.push_str(&format!(" {}", i));
        }
        obj.push_str("\n");

        // 顶面（顺时针）
        obj.push_str("\n# Top face\n");
        obj.push_str("f");
        for i in 1..=n {
            obj.push_str(&format!(" {}", i + n));
        }
        obj.push_str("\n");

        // 侧面
        obj.push_str("\n# Side faces\n");
        for i in 0..n {
            let next = (i + 1) % n;
            let v1 = i + 1;
            let v2 = next + 1;
            let v3 = v2 + n;
            let v4 = v1 + n;

            // 每个侧面用两个三角形
            obj.push_str(&format!("f {} {} {}\n", v1, v2, v3));
            obj.push_str(&format!("f {} {} {}\n", v1, v3, v4));
        }

        println!("✅ truck工作流3D模型生成完成");
        Ok(obj)
    }

    /// 生成OBJ格式的3D模型
    fn generate_obj(&self) -> String {
        let mut obj = String::new();
        obj.push_str("# PLOOP 3D Model\n");
        obj.push_str(&format!("# Name: {}\n", self.name));
        obj.push_str(&format!("# Height: {:.1}mm\n", self.height));
        obj.push_str(&format!("# Vertices: {}\n", self.vertices.len()));
        obj.push_str(&format!("# FRADIUS count: {}\n\n", self.fradius_count));

        // 转换单位：毫米 -> 米
        let scale = 0.001;
        let height = self.height * scale;

        // 生成底面顶点
        obj.push_str("# Bottom face vertices\n");
        for vertex in &self.vertices {
            obj.push_str(&format!("v {:.6} {:.6} 0.0\n",
                vertex.x * scale, vertex.y * scale));
        }

        // 生成顶面顶点
        obj.push_str("\n# Top face vertices\n");
        for vertex in &self.vertices {
            obj.push_str(&format!("v {:.6} {:.6} {:.6}\n",
                vertex.x * scale, vertex.y * scale, height));
        }

        // 生成面
        let n = self.vertices.len();

        // 底面（逆时针）
        obj.push_str("\n# Bottom face\n");
        obj.push_str("f");
        for i in (1..=n).rev() {
            obj.push_str(&format!(" {}", i));
        }
        obj.push_str("\n");

        // 顶面（顺时针）
        obj.push_str("\n# Top face\n");
        obj.push_str("f");
        for i in 1..=n {
            obj.push_str(&format!(" {}", i + n));
        }
        obj.push_str("\n");

        // 侧面
        obj.push_str("\n# Side faces\n");
        for i in 0..n {
            let next = (i + 1) % n;
            let v1 = i + 1;
            let v2 = next + 1;
            let v3 = v2 + n;
            let v4 = v1 + n;

            // 每个侧面用两个三角形
            obj.push_str(&format!("f {} {} {}\n", v1, v2, v3));
            obj.push_str(&format!("f {} {} {}\n", v1, v3, v4));
        }

        obj
    }

    /// 生成STL格式的3D模型
    fn generate_stl(&self) -> String {
        let mut stl = String::new();
        stl.push_str(&format!("solid {}\n", self.name.replace("/", "_")));

        // 转换单位：毫米 -> 米
        let scale = 0.001;
        let height = self.height * scale;

        let vertices: Vec<(f64, f64)> = self.vertices.iter()
            .map(|v| (v.x * scale, v.y * scale))
            .collect();

        let n = vertices.len();

        // 底面三角形（逆时针）
        for i in 1..n-1 {
            let v0 = &vertices[0];
            let v1 = &vertices[i];
            let v2 = &vertices[i + 1];

            stl.push_str("  facet normal 0.0 0.0 -1.0\n");
            stl.push_str("    outer loop\n");
            stl.push_str(&format!("      vertex {:.6} {:.6} 0.0\n", v0.0, v0.1));
            stl.push_str(&format!("      vertex {:.6} {:.6} 0.0\n", v2.0, v2.1));
            stl.push_str(&format!("      vertex {:.6} {:.6} 0.0\n", v1.0, v1.1));
            stl.push_str("    endloop\n");
            stl.push_str("  endfacet\n");
        }

        // 顶面三角形（顺时针）
        for i in 1..n-1 {
            let v0 = &vertices[0];
            let v1 = &vertices[i];
            let v2 = &vertices[i + 1];

            stl.push_str("  facet normal 0.0 0.0 1.0\n");
            stl.push_str("    outer loop\n");
            stl.push_str(&format!("      vertex {:.6} {:.6} {:.6}\n", v0.0, v0.1, height));
            stl.push_str(&format!("      vertex {:.6} {:.6} {:.6}\n", v1.0, v1.1, height));
            stl.push_str(&format!("      vertex {:.6} {:.6} {:.6}\n", v2.0, v2.1, height));
            stl.push_str("    endloop\n");
            stl.push_str("  endfacet\n");
        }

        // 侧面
        for i in 0..n {
            let next = (i + 1) % n;
            let v1 = &vertices[i];
            let v2 = &vertices[next];

            // 计算法向量（简化）
            let dx = v2.0 - v1.0;
            let dy = v2.1 - v1.1;
            let len = (dx * dx + dy * dy).sqrt();
            let nx = if len > 0.0 { -dy / len } else { 0.0 };
            let ny = if len > 0.0 { dx / len } else { 0.0 };

            // 第一个三角形
            stl.push_str(&format!("  facet normal {:.6} {:.6} 0.0\n", nx, ny));
            stl.push_str("    outer loop\n");
            stl.push_str(&format!("      vertex {:.6} {:.6} 0.0\n", v1.0, v1.1));
            stl.push_str(&format!("      vertex {:.6} {:.6} 0.0\n", v2.0, v2.1));
            stl.push_str(&format!("      vertex {:.6} {:.6} {:.6}\n", v2.0, v2.1, height));
            stl.push_str("    endloop\n");
            stl.push_str("  endfacet\n");

            // 第二个三角形
            stl.push_str(&format!("  facet normal {:.6} {:.6} 0.0\n", nx, ny));
            stl.push_str("    outer loop\n");
            stl.push_str(&format!("      vertex {:.6} {:.6} 0.0\n", v1.0, v1.1));
            stl.push_str(&format!("      vertex {:.6} {:.6} {:.6}\n", v2.0, v2.1, height));
            stl.push_str(&format!("      vertex {:.6} {:.6} {:.6}\n", v1.0, v1.1, height));
            stl.push_str("    endloop\n");
            stl.push_str("  endfacet\n");
        }

        stl.push_str("endsolid\n");
        stl
    }
}

/// 主函数
fn main() -> Result<()> {
    println!("🚀 PLOOP 3D模型批量生成器启动");

    // 确保输出目录存在
    fs::create_dir_all("../obj")?;
    fs::create_dir_all("../stl")?;

    // 查找所有JSON数据文件
    let json_files = [
        ("K717", "../rust-svg/k717_data.json"),
        ("K718", "../rust-svg/k718_data.json"),
        ("K716", "../rust-svg/k716_data.json"),
        ("K701", "../rust-svg/k701_data.json"),
    ];

    let mut processed_count = 0;

    for (case_name, json_file) in &json_files {
        if Path::new(json_file).exists() {
            println!("\n🔧 处理案例: {}", case_name);
            println!("加载数据文件: {}", json_file);

            // 加载PLOOP数据
            let ploop_data = PlotData::load_from_file(json_file)?;

            println!("✅ 数据加载成功！");
            println!("- 案例名称: {}", ploop_data.name);
            println!("- 拉伸高度: {:.1}mm", ploop_data.height);
            println!("- 顶点数量: {}", ploop_data.vertices.len());
            println!("- FRADIUS数量: {}", ploop_data.fradius_count);

            // 生成3D模型文件
            let safe_case_name = case_name.to_lowercase();

            // 生成基础OBJ文件到obj目录
            let obj_content = ploop_data.generate_obj();
            let obj_filename = format!("../obj/{}_3d_model.obj", safe_case_name);
            fs::write(&obj_filename, obj_content)?;
            println!("📦 基础OBJ文件已生成: {}", obj_filename);

            // 生成带FRADIUS圆弧细分的高质量OBJ文件
            if ploop_data.fradius_count > 0 {
                match ploop_data.generate_truck_obj() {
                    Ok(truck_obj_content) => {
                        let truck_obj_filename = format!("../obj/{}_fradius_3d_model.obj", safe_case_name);
                        fs::write(&truck_obj_filename, truck_obj_content)?;
                        println!("📦 FRADIUS高质量OBJ文件已生成: {}", truck_obj_filename);
                    }
                    Err(e) => {
                        println!("⚠️  truck工作流失败: {}", e);
                        println!("🔄 回退到FRADIUS细分方法...");

                        // 回退到已经成功的FRADIUS细分方法
                        match ploop_data.generate_subdivided_obj() {
                            Ok(fradius_obj_content) => {
                                let fradius_obj_filename = format!("../obj/{}_fradius_3d_model.obj", safe_case_name);
                                fs::write(&fradius_obj_filename, fradius_obj_content)?;
                                println!("📦 FRADIUS细分OBJ文件已生成: {}", fradius_obj_filename);
                            }
                            Err(e2) => {
                                println!("❌ FRADIUS细分也失败: {}", e2);
                            }
                        }
                    }
                }
            } else {
                println!("ℹ️  该案例无FRADIUS圆弧，跳过高质量版本");
            }

            // 生成STL文件到stl目录
            let stl_content = ploop_data.generate_stl();
            let stl_filename = format!("../stl/{}_3d_model.stl", safe_case_name);
            fs::write(&stl_filename, stl_content)?;
            println!("📦 STL文件已生成: {}", stl_filename);

            // 显示模型统计信息
            let n = ploop_data.vertices.len();
            let triangles = (n - 2) * 2 + (n * 2); // 底面 + 顶面 + 侧面
            println!("📊 模型统计:");
            println!("- 顶点数: {} (底面) + {} (顶面) = {}", n, n, n * 2);
            println!("- 三角形数: {}", triangles);
            println!("- 体积估算: {:.2} 立方米", calculate_volume(&ploop_data));

            processed_count += 1;
            println!("✅ {} 3D模型生成完成", case_name);
        } else {
            println!("⚠️  跳过案例 {}: 数据文件不存在 ({})", case_name, json_file);
        }
    }

    println!("\n🎉 批量3D模型生成完成！");
    println!("成功处理 {} 个案例", processed_count);
    println!("\n您可以使用以下软件查看3D模型:");
    println!("- OBJ文件: Blender, MeshLab, 3D Viewer");
    println!("- STL文件: 3D打印软件, Blender, MeshLab");
    println!("\n生成的文件位置:");
    println!("- OBJ文件: ../obj/ 目录");
    println!("- STL文件: ../stl/ 目录");
    println!("- JSON数据: ../rust-svg/ 目录");
    println!("- SVG截面: ../rust-svg/ 目录");

    Ok(())
}

/// 计算体积（简化估算）
fn calculate_volume(data: &PlotData) -> f64 {
    // 使用鞋带公式计算底面积
    let mut area = 0.0;
    let n = data.vertices.len();

    for i in 0..n {
        let j = (i + 1) % n;
        let xi = data.vertices[i].x * 0.001; // 转换为米
        let yi = data.vertices[i].y * 0.001;
        let xj = data.vertices[j].x * 0.001;
        let yj = data.vertices[j].y * 0.001;

        area += xi * yj - xj * yi;
    }

    area = area.abs() / 2.0;
    let height = data.height * 0.001; // 转换为米

    area * height
}
